/**
 * Licensed under The MIT License
 *  Copyright (c) 2011 Han Wen
 *  
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included in
 *  all copies or substantial portions of the Software.
 *  
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *  THE SOFTWARE.
 **/

package edu.rochester.URshuttleschedule;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.GradientDrawable.Orientation;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class OverView extends ListActivity {
	private ListView lv1;
	private int TabId;
	private ArrayList<String> listDsp;
	private ArrayList<Integer> timeCol;
	private String[] dt;
	private String[] schedule;
	private String[] stations;
	private String[] wholeSchedule;
	int[] schHour;
	int[] schMinute;
	private int[] background;
	private int nextBus = -1;
	private String indicator;
	Bundle bundle;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		bundle = this.getIntent().getExtras();
		TabId = bundle.getInt("TabId");
		indicator = URshuttleschedule.indicator;
		setContentView(R.layout.listview);
		lv1 = (ListView) findViewById(android.R.id.list);
		lv1.setDivider(new GradientDrawable(Orientation.RIGHT_LEFT,
				URshuttleschedule.listDividerColor));
		lv1.setDividerHeight(2);
		lv1.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position,
					long id) {
				Intent details = new Intent(view.getContext(),
						DetailedSchedule.class);
				bundle.putStringArray("schedule", wholeSchedule);
				bundle.putStringArray("stations", stations);
				bundle.putString("myLocation",
						URshuttleschedule.getMyLocation());
				bundle.putInt("col", timeCol.get(position));
				details.putExtras(bundle);
				startActivity(details);
			}
		});
		if (memoryAllocation()) {
			polulateTimeList();
			findNextBus(0);
			calcTimeRemained();
			setBackground(0, listDsp.size());
		}
		lv1.setAdapter(new EfficientAdapter(this));
		lv1.setSelection(nextBus);
	}

	private boolean memoryAllocation() {
		stations = getResources().getStringArray(
				URshuttleschedule.getStation(TabId));
		wholeSchedule = getResources().getStringArray(
				URshuttleschedule.getSchedule(TabId));
		int index = Arrays.asList(stations).indexOf(
				URshuttleschedule.getMyLocation());
		if (index == -1)
			schedule = wholeSchedule[0].split(",");
		else
			schedule = wholeSchedule[index].split(",");
		int numItems = schedule.length;
		listDsp = new ArrayList<String>(numItems);
		timeCol = new ArrayList<Integer>(numItems);
		schHour = new int[numItems];
		schMinute = new int[numItems];
		background = new int[numItems];
		dt = new String[numItems];
		if (index == -1)
			return false;
		return true;
	}

	private void setBackground(int start, int end) {
		int nextBusTmp = (nextBus == -1) ? end : nextBus;
		switch (URshuttleschedule.lineCode) {
		case 1: // blue
		default: {
			int date = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
			if (Calendar.SUNDAY == date || Calendar.SATURDAY == date) {
				for (int k = start; k < nextBusTmp; k++)
					background[k] = R.drawable.text_bg_fadednormal;
				for (int k = nextBusTmp; k < end; k++)
					background[k] = R.drawable.text_bg_blue;
			} else
				setBackgroundUtil(start, end, nextBusTmp,
						R.drawable.text_bg_blue,
						R.drawable.text_bg_fadednormal,
						R.drawable.text_bg_blueviahospital,
						R.drawable.text_bg_fadedblue);
			break;
		}
		case 2: // red
			for (int k = start; k < nextBusTmp; k++)
				background[k] = R.drawable.text_bg_fadednormal;
			for (int k = nextBusTmp; k < end; k++)
				background[k] = R.drawable.text_bg_red;
			break;
		case 3: { // gold
			int date = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
			if (Calendar.SUNDAY == date || Calendar.SATURDAY == date) {
				for (int k = start; k < nextBusTmp; k++)
					background[k] = R.drawable.text_bg_fadednormal;
				for (int k = nextBusTmp; k < end; k++)
					background[k] = R.drawable.text_bg_gold;
			} else setBackgroundUtil(start, end, nextBusTmp,
					R.drawable.text_bg_golddirect,
					R.drawable.text_bg_fadedgold, R.drawable.text_bg_gold,
					R.drawable.text_bg_fadednormal);
			break;
		}
		case 4: {// green
			int date = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
			if (Calendar.SATURDAY == date)
				setBackgroundUtil(start, end, nextBusTmp,
						R.drawable.text_bg_green,
						R.drawable.text_bg_fadednormal,
						R.drawable.text_bg_greentopublicmarket,
						R.drawable.text_bg_fadedgreen);
			else {
				for (int k = start; k < nextBusTmp; k++)
					background[k] = R.drawable.text_bg_fadednormal;
				for (int k = nextBusTmp; k < end; k++)
					background[k] = R.drawable.text_bg_green;
			}
			break;
		}
		case 7: // reserve for summer/winter break
			for (int k = start; k < nextBusTmp; k++) {
				background[k] = R.drawable.text_bg_fadednormal;
			}
			for (int k = nextBusTmp; k < end; k++) {
				background[k] = R.drawable.text_bg_blue;
			}
			break;
		}
	}

	private void setBackgroundUtil(int start, int end, int nextBusTmp, int nor,
			int faded, int nor2, int faded2) {
		int[] isDirect = getResources().getIntArray(
				URshuttleschedule.getIsDirect(TabId));
		for (int k = start; k < nextBusTmp; k++) {
			if (isDirect[timeCol.get(k)] == 1)
				background[k] = faded;
			else
				background[k] = faded2;
		}
		for (int k = nextBusTmp; k < end; k++) {
			if (isDirect[timeCol.get(k)] == 1)
				background[k] = nor;
			else
				background[k] = nor2;
		}
	}

	private void findNextBus(int start) {
		if (start < 0)
			start = 0;
		final Calendar c = Calendar.getInstance();
		int hour = c.get(Calendar.HOUR_OF_DAY);
		int minute = c.get(Calendar.MINUTE);
		int tempT;
		for (int k = start; k < listDsp.size(); k++) {
			if (hour <= schHour[k]) {
				if (hour < schHour[k] - 1) {
					dt[k] = "    " + Integer.toString(schHour[k] - hour)
							+ " Hr    ";
					nextBus = k;
					break;
				} else {
					tempT = ((schHour[k] - hour) == 0 ? 0 : 60) + schMinute[k]
							- minute;
					if (tempT >= 0) {
						dt[k] = "    " + Integer.toString(tempT) + "Min    ";
						nextBus = k;
						break;
					} else {
						dt[k] = indicator;
					}
				}
			} else {
				dt[k] = indicator;
			}
		}
	}

	public void reload() {
		lv1.setDivider(new GradientDrawable(Orientation.RIGHT_LEFT,
				URshuttleschedule.listDividerColor));
		lv1.setDividerHeight(2);
		if (memoryAllocation()) {
			nextBus = -1;
			polulateTimeList();
			findNextBus(0);
			calcTimeRemained();
			setBackground(0, listDsp.size());
			lv1.setSelection(nextBus);
		} else {
			listDsp.clear();
			timeCol.clear();
		}
		((BaseAdapter) lv1.getAdapter()).notifyDataSetChanged();
	}

	@Override
	public void onResume() {
		super.onResume();

		int nextBusOld = nextBus;
		findNextBus(nextBusOld);
		if (nextBusOld == nextBus)
			return;
		calcTimeRemained();
		setBackground(nextBusOld, -1);
		lv1.setSelection(nextBus);
	}

	protected class EfficientAdapter extends BaseAdapter implements ListAdapter {
		private LayoutInflater mInflater;

		public EfficientAdapter(Context context) {
			mInflater = LayoutInflater.from(context);

		}

		public int getCount() {
			return listDsp.size();
		}

		public Object getItem(int position) {
			return position;
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder holder;
			if (convertView == null) {
				convertView = mInflater.inflate(R.layout.listcontent, null);
				holder = new ViewHolder();
				holder.text = (TextView) convertView
						.findViewById(R.id.TextView01);
				holder.text2 = (TextView) convertView
						.findViewById(R.id.TextView02);
				convertView.setTag(holder);
			} else {
				holder = (ViewHolder) convertView.getTag();
			}

			holder.text.setText(dt[position]);
			holder.text2.setText(listDsp.get(position));
			holder.text.setId(position);
			// holder.more.setId(position);
			if (position > nextBus) {
				holder.text2.setTextColor(0xfffefefe);
				holder.text2.setShadowLayer(1.8f, 1.2f, 1.2f, 0xffffffff);
			} else {
				if (position < nextBus) {
					holder.text2.setTextColor(0xff4e4e4e);
					holder.text2.setShadowLayer(0.0f, 0.0f, 0.0f, 0);
				} else {
					holder.text2.setTextColor(0xffff0000);
					holder.text2.setShadowLayer(1.8f, 0.8f, 0.8f, 0xffff0000);
				}
			}
			holder.text.setBackgroundResource(background[position]);
			return convertView;
		}

	}

	static class ViewHolder {
		TextView text;
		TextView text2;
	}

	public void changeLocation(String stationName) {
		int index = Arrays.asList(stations).indexOf(stationName);
		if (index == -1) {
			listDsp.clear();
			timeCol.clear();
			((BaseAdapter) lv1.getAdapter()).notifyDataSetChanged();
			return;
		}
		schedule = wholeSchedule[index].split(",");
		polulateTimeList();
		findNextBus(0);
		calcTimeRemained();
		setBackground(0, listDsp.size());
		((BaseAdapter) lv1.getAdapter()).notifyDataSetChanged();
		lv1.setSelection(nextBus);
	}

	private void polulateTimeList() {
		listDsp.clear();
		timeCol.clear();
		for (int k = 0; k < schedule.length; k++) {
			if (!schedule[k].equals("-")) {
				listDsp.add(schedule[k]);
				timeCol.add(k);
				continue;
			}
		}
		// convert 24 hour format to 12 hour format
		for (int k = 0; k < listDsp.size(); k++) {
			String[] splitTime = listDsp.get(k).split(":");
			schHour[k] = Integer.parseInt(splitTime[0]);
			schMinute[k] = Integer.parseInt(splitTime[1]);
			if (schHour[k] < 12) {
				if (schHour[k] == 0) {
					listDsp.set(k, Integer.toString(12) + ":" + splitTime[1]
							+ " AM");
					continue;
				}
				listDsp.set(k, listDsp.get(k) + " AM");
			} else {
				listDsp.set(
						k,
						Integer.toString((schHour[k] != 12) ? schHour[k] - 12
								: 12) + ":" + splitTime[1] + " PM");
			}
		}
	}
	
	// This function can only be called after findNextBus()
	private void calcTimeRemained() {
		final Calendar c = Calendar.getInstance();
		int hour = c.get(Calendar.HOUR_OF_DAY);
		int minute = c.get(Calendar.MINUTE);
		for (int k = nextBus + 1; k < listDsp.size(); k++) {
			if (hour < schHour[k] - 1)
				dt[k] = "    " + Integer.toString(schHour[k] - hour)
						+ " Hr    ";
			else
				dt[k] = "    "
						+ Integer.toString(((schHour[k] - hour) == 0 ? 0 : 60)
								+ schMinute[k] - minute) + "Min    ";
		}
	}

}